package controllers

/**
 * Created by yz on 2017/5/31.
 */

import command.CommandExec
import dao._
import implicits.Implicits._
import play.api.mvc._
import shared.Pojo._
import shared.tsPojo.TsPojo
import tool.{FormTool, Tool}
import tool.Pojo.CommandData
import ujson.play.PlayJson
import upickle.default._
import utils.Utils

import java.io.File
import javax.inject.Inject
import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global

class BrowseCircController @Inject()(cc: ControllerComponents)(
  implicit val basicDao: BrowseCircDao,
  implicit val hTissueDataDao: HTissueDataDao,
  implicit val modeDao: ModeDao,
  implicit val hcircCpmDao: HcircCpmDao,
  implicit val mTissueDataDao: MTissueDataDao,
) extends AbstractController(cc) {

  import TsPojo.browseCirc._

  def allByServer = Action.async { implicit request =>
    val obj = PlayJson.transform(request.body.asJson.get, reader[ujson.Obj])
    val pageData = FormTool.pageForm.bindFromRequest().get
    basicDao.selectAll(obj.value, pageData).map { case (size, x) =>
      val array = Utils.getJsonByTs(x)
      Ok(ujson.Obj("rows" -> array, "total" -> size))
    }
  }

  def allGeneSymbol = Action.async { implicit request =>
    basicDao.selectAllGeneSymbol.map { x =>
      Ok(writeJs(x))
    }
  }

  def allChr = Action.async { implicit request =>
    basicDao.selectAllChr.map { x =>
      val numX = x.map { x =>
        (x, x.replaceAll("^chr", ""))
      }.filter { x =>
        x._2.isInt
      }.sortBy { x =>
        x._2.toInt
      }.map(_._1)
      val nanX = x.filterNot { x =>
        numX.contains(x)
      }.sorted
      Ok(writeJs((numX ::: nanX)))
    }
  }

  def search = Action.async { implicit request =>
    val data = PlayJson.transform(request.body.asJson.get, reader[CircSearch.Request])
    basicDao.search(data).map { x =>
      val array = Utils.getArrayByTs(x)
      Ok(writeJs(array))
    }
  }

  def allGeneAsync = Action.async { implicit request =>
    val data = FormTool.qForm.bindFromRequest().get
    val pageSize = data.pageSize
    basicDao.selectAllGene(data).map { x =>
      val trueX = x.sorted.sortWith((t, z) => {
        (data.q.size.toDouble / t.size) > (data.q.size.toDouble / z.size)
      }).drop((data.page - 1) * pageSize).take(pageSize)
      val results = trueX.map { y =>
        ujson.Obj("id" -> y, "text" -> y)
      }
      val more = pageSize * data.page < x.size
      Ok(ujson.Obj("results" -> results, "pagination" -> ujson.Obj("more" -> more)))
    }
  }

  def circId2GeneName = Action.async { implicit request =>
    val data = PlayJson.transform(request.body.asJson.get, reader[CircId2GeneName.Request])
    basicDao.select(data.circId).map { x =>
      Ok(ujson.Str(x.geneSymbol))
    }
  }

  def hTissueBoxplotImage = Action.async { implicit request =>
    val startTime = System.currentTimeMillis()
    val data = PlayJson.transform(request.body.asJson.get, reader[HTissueBoxplotImage.Request])
    val circId = data.circId
    hcircCpmDao.selectAll(circId).map { rows =>
      val tmpDir = Tool.createTempDirectory("tmpDir")
      val pngFile = new File(tmpDir, "out.png")
      val inputFile = new File(tmpDir, "input.csv")
      val maps = rows.map { row =>
        SeqMap("circID" -> row.circId) ++ Tool.json2SeqMap(row.value)
      }.toList
      maps.csvLines.toFile(inputFile)
      val metaFile = new File(Tool.dataDir, "hcirc_meta_848S.txt")
      val colorFile = new File(Tool.dataDir, "boxplot_pal.txt")
      val command =
        s"""
           |${"Rscript".condaPath()} ${Tool.rPath.unixPath}/hcirc_expr.R --i ${inputFile.unixPath} --m ${metaFile.unixPath} --c ${colorFile.unixPath} --g ${data.group} --p "${data.phenotypes.mkString(";")}" --d "${data.datasets.mkString(";")}" --l ${data.log} --o ${pngFile.unixPath}
           |""".stripMargin
      val commandExec = CommandExec().exec { b =>
        CommandData(tmpDir, command)
      }
      val response = if (commandExec.isSuccess) {
        println("exec complete:", Utils.getTime(startTime))
        val base64 = pngFile.base64
        val geneData = new File(tmpDir, "gene.csv").str
        HTissueBoxplotImage.Response(valid = true, base64 = base64, geneData = geneData)
      } else {
        HTissueBoxplotImage.Response(valid = false, message = commandExec.errorInfo)
      }
      Tool.deleteDirectory(tmpDir)
      Ok(writeJs(response))
    }

  }

  def mTissueBoxplotImage = Action { implicit request =>
    val startTime = System.currentTimeMillis()
    val data = PlayJson.transform(request.body.asJson.get, reader[MTissueBoxplotImage.Request])
    val tmpDir = Tool.createTempDirectory("tmpDir")
    val pngFile = new File(tmpDir, "mbulk_expr_default.png")
    val inputFile = new File(Tool.dataDir, "mcirc_cpm_113S_R1.txt")
    val metaFile = new File(Tool.dataDir, "mcirc_meta_113S.txt")
    val colorFile = new File(Tool.dataDir, "boxplot_pal.txt")
    val command =
      s"""
         |${"Rscript".condaPath()} ${Tool.rPath.unixPath}/mcirc_expr.R --i ${inputFile.unixPath} --m ${metaFile.unixPath} --c ${colorFile.unixPath} --g ${data.group} --p "${data.phenotypes.mkString(";")}" --d "${data.datasets.mkString(";")}" --model "${data.models.mkString("@@@")}" --l ${data.log} --circId ${data.circId}  --o ${pngFile.unixPath}
         |""".stripMargin
    val commandExec = CommandExec().exec { b =>
      CommandData(tmpDir, command)
    }
    val response = if (commandExec.isSuccess) {
      println("exec complete:", Utils.getTime(startTime))
      val base64 = pngFile.base64
      val geneData = new File(tmpDir, "gene.csv").str
      MTissueBoxplotImage.Response(valid = true, base64 = base64, geneData = geneData)
    } else {
      MTissueBoxplotImage.Response(valid = false, message = commandExec.errorInfo)
    }
    println(tmpDir.unixPath)
    Tool.deleteDirectory(tmpDir)
    Ok(writeJs(response))
  }


}
